﻿using System;
using System.Data;
using System.IO;
using Ext.Net;
using Sunny.Core.DefinedData;
using Sunny.Core.Domain;
using Sunny.Core.Domain.Model;
using Sunny.Core.Domain.Repository;
using Sunny.Core.Exception.Domain;

namespace Sunny.Web
{
    public abstract class BasePage : System.Web.UI.Page, IBasePage
    {
        public const string Parameter = "Parameter";

        #region Page Load

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            AfterInit();
        }

        protected override void OnPreInit(EventArgs e)
        {
            this.CheckLogin();

            base.OnPreInit(e);
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                this.BindPageParam();

                this.LoadPage();
            }

            if (!X.IsAjaxRequest)
            {
                this.AjaxLoadPage();
            }
        }

        protected virtual void AfterInit()
        {
            //
        }

        protected virtual void LoadPage()
        {
            //
        }

        protected virtual void AjaxLoadPage()
        {
        }

        #endregion

        #region Current Login

        ICurrentLogin IBasePage.CurrentLogin
        {
            get { return this.GetCurrentLogin(); }
            set { this.SetCurrentLogin(value); }
        }

        protected abstract ICurrentLogin GetCurrentLogin();
        protected abstract void SetCurrentLogin(ICurrentLogin currentLogin);

        #endregion

        protected override void RaisePostBackEvent(System.Web.UI.IPostBackEventHandler sourceControl, string eventArgument)
        {
            try
            {
                base.RaisePostBackEvent(sourceControl, eventArgument);
            }
            catch (DataException ex)
            {
                ShowErrorMessage(ex);
            }
            catch (DomainException ex)
            {
                ShowErrorMessage(ex);
            }
        }

        protected virtual void ShowErrorMessage(System.Exception ex)
        {
            Msg.Alert("Error", ex.Message);
        }

        protected virtual void BindPageParam()
        {
            // do nonthing
        }

        #region Check Login

        protected virtual void CheckLogin()
        {
            if(this.GetCurrentLogin() == null)
            {
                this.PageTransfer(this.GetSessionExpiryUrl());
            }
        }

        protected abstract string GetSessionExpiryUrl();

        #endregion

        #region Page Transfer

        protected virtual void PageTransfer(string url)
        {
            PageTransfer(url, null);
        }

        protected virtual void PageTransfer(string url, IPageParameter param)
        {
            this.Response.Redirect(this.GetPageUrl(url, param));
        }

        protected virtual void ParentPageTransfer(string url, Ext.Net.XControl control)
        {
            this.ParentPageTransfer(url, null, control);
        }

        protected virtual void ParentPageTransfer(string url, IPageParameter param, Ext.Net.XControl control)
        {
            control.AddScript("parent.window.location.href='" + this.GetPageUrl(url, param) + "'");
        }

        protected string GetPageUrl(string url)
        {
            return this.GetPageUrl(url, null);
        }

        protected string GetPageUrl(string url, IPageParameter param)
        {
            if (param != null)
            {
                var paramString = AppNavigate.GetParamString(param);

                url = url + paramString;
            }

            return this.Request.ApplicationPath + url;
        }

        #endregion

        #region Download

        public void DownloadDocument(SFile file, string expectFileName)
        {
            this.DownloadDocument(file, expectFileName, false);
        }

        public void DownloadDocument(SFile file, string expectFileName, bool isNeedDeleteFile)
        {
            Response.Clear();
            if (string.IsNullOrEmpty(expectFileName))
            {
                Response.AddHeader("content-disposition", string.Format("attachment;filename={0}", file.FileName));
            }
            else
            {
                Response.AddHeader("content-disposition",
                                   string.Format("attachment;filename={0}{1}", expectFileName, file.Extension));
            }
            Response.Charset = "";
            switch (file.Extension.ToLower())
            {
                case ".doc":
                    Response.ContentType = "application/msword";
                    break;
                case ".docx":
                    Response.ContentType = "application/msword";
                    break;
                case ".pdf":
                    Response.ContentType = "application/vnd.pdf";
                    break;
            }
            Response.WriteFile(file.PhysicalPath);
            Response.Flush();
            Response.Close();

            // Delete temporary file
            if (isNeedDeleteFile && File.Exists(file.PhysicalPath))
            {
                File.Delete(file.PhysicalPath);
            }
        }

        #endregion
    }

    public abstract class BasePage<T> : BasePage
        where T : IPageParameter, new()
    {
        public T Parameters
        {
            get
            {
                if (ViewState[Parameter] == null)
                {
                    ViewState[Parameter] = new T();
                }

                return (T)ViewState[Parameter];
            }
        }

        protected override void BindPageParam()
        {
            string query = Request.QueryString.ToString();

            AppNavigate.BindPageParam(query, this.Parameters);
        }
    }
}
